/*
 * Copyright (C) 2010 Yellow_Panther
 * 
 * yanick.saugy@gmail.com - http://www.help-info.ch
 *
 *     This file is part of BTRemote.
 *
 *    BTRemote is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    BTRemote is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with BTRemote.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package ch.yp.android.btremote;

import it.gerdavax.android.bluetooth.*;

import java.io.*;
import java.util.*;

import android.app.*;
import android.content.*;
import android.content.pm.*;
import android.os.*;
import android.view.*;

/**
 * 
 * @author Yellow_Panther
 * @version 0.1
 */
public class Remote extends Activity implements DialogInterface.OnClickListener  {
	private OutputStream output;
	private LocalBluetoothDevice localBTDevice;
	private String devices[];
	private boolean btPresent;
	private DeviceAdapter adapter;
	private String devAddress="";
	ProgressDialog dialog;

	/* Constants from default keyboard.xml */
	private final int BACK      	=0x08;
	private final int REWIND    	='r';
	private final int FORWARD   	='f';
	private final int NEXT      	='.';
	private final int PREVIOUS  	=',';
	private final int PLAY      	='p'; //play/pause
	private final int STOP      	='x';
	private final int FULLSCREEN	=0x09;
	private final int MENU			='m';
	private final int INFO			='i';
	private final int CONTEXTMENU	='c';
	
	/* constants added for non-representable char
	   they have to be converted in python script */
	private final int UP        =0xA0;
	private final int DOWN      =0xA1;
	private final int LEFT      =0xA2;
	private final int RIGHT     =0xA3;
	private final int MUTE      =0xA4;
	private final int ENTER     =0xA5;
	private final int VOL_DOWN  =0xA6;
	private final int VOL_UP    =0xA7;

	/**
	 * 
	 * @author panther
	 *
	 */
	private class DeviceAdapter implements LocalBluetoothDeviceListener, DialogInterface.OnClickListener {

		public void scanCompleted(ArrayList<String> devs) {
			dialog.dismiss();
			if(true){
				devices = new String[devs.size()];
					for(int i=0;i<devs.size();i++){
						try{
							devices[i]=devs.get(i)+"\n"+localBTDevice.getRemoteBluetoothDevice(devs.get(i)).getName();
						}
						catch (BluetoothException bte){
						}
					}

				AlertDialog.Builder builder = new AlertDialog.Builder(Remote.this);
				builder.setTitle(getString(R.string.select_bt_dev));
				builder.setItems(devices, this);
				AlertDialog alert = builder.create();
				alert.show();
			}
		}
		
		public void scanStarted() {
			showWaitDialog(R.string.scanning);
		}

		@Override
		public void bluetoothDisabled() {
			BTRemote.tooltip(getApplicationContext(), getString(R.string.bt_disabled_ok));
		}

		@Override
		public void bluetoothEnabled() {
			try {
				localBTDevice.scan();
			} catch (Exception e) {
				BTRemote.tooltip(getApplicationContext(), "Scan error after enabling BT.");
			}
		}

		@Override
		public void deviceFound(String arg0) {
			// TODO Auto-generated method stub
		}

		@Override
		public void onClick(DialogInterface arg0, int item) {
			devAddress=devices[item].substring(0,17);
			arg0.dismiss();
			pair(devAddress);
		}
	}

	/**
	 * 
	 * @author panther
	 *
	 */
	private class RemoteBluetoothDeviceEventHandler implements RemoteBluetoothDeviceListener{
		RemoteBluetoothDevice device;

		public void paired() {
			// connects to channel 1
			connectTo(device, 20);
		}

		public void pinRequested() {
			BTRemote.tooltip(getApplicationContext(), getString(R.string.pin_requested));
		}

		public void gotServiceChannel(int serviceID, int channel) {
			// TODO Auto-generated method stub
		}

		public void serviceChannelNotAvailable(int serviceID) {
			// TODO Auto-generated method stub
		}

	}

	private void init(){
		output=null;
		localBTDevice=null;
		devices=null;
		btPresent=false;
		adapter=null;
		dialog=null;
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		init();
		dialog=new ProgressDialog(this);

		setContentView(R.layout.remote);
		adapter = new DeviceAdapter();
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

		try {
			localBTDevice = LocalBluetoothDevice.initLocalDevice(this);
			btPresent=true;

			if (localBTDevice.isEnabled()) {
				localBTDevice.setListener(adapter);
			} else {
				AlertDialog.Builder builder = new AlertDialog.Builder(Remote.this);

				builder.setMessage(getString(R.string.turn_bt_on_question));
				builder.setCancelable(false);
				builder.setPositiveButton("Yes", this);
				builder.setNegativeButton("No", this);
				AlertDialog alert = builder.create();
				alert.show();
			}
		} catch (Exception e) {
			BTRemote.tooltip(getApplicationContext(), "No bluetooth adapter found.");
		}
	}

	@Override
	protected void onDestroy() {
		if(btPresent)
			localBTDevice.close();
		super.onDestroy();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		super.onSaveInstanceState(outState);
		outState.putString("devAddress", devAddress);
	}
	
	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onRestoreInstanceState(savedInstanceState);
		devAddress=savedInstanceState.getString("devAddress");
		if(devAddress!="")
			pair(devAddress);
		else{
			try {
				localBTDevice.scan();
			} catch (Exception e) {
				BTRemote.tooltip(getApplicationContext(), "Erreur scan");
			}
		}
	}
	/**
	 * 
	 * @param address
	 */
	private void pair(String address) {
		RemoteBluetoothDevice device = localBTDevice.getRemoteBluetoothDevice(address);
		RemoteBluetoothDeviceEventHandler listener = new RemoteBluetoothDeviceEventHandler();
		listener.device = device;
		device.setListener(listener);
		device.pair();
	}

	/**
	 * 
	 * @param device
	 * @param port
	 */
	private void connectTo(final RemoteBluetoothDevice device, final int port) {
		BluetoothSocket socket;
		try {
			socket = device.openSocket(port);
			output = socket.getOutputStream();
			output.write("HTC".getBytes());
		} catch (BluetoothException e) {
			BTRemote.showDialog(getBaseContext(), R.string.error_connect);
		} catch (Exception e){
			BTRemote.tooltip(getApplicationContext(), "Error creating outputstream.");
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.remote, menu);
        return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		try{
			switch(item.getItemId()) {
			case R.id.mnuSearch:
				localBTDevice.scan();
	        	return true;
			case R.id.mnuBt_en:
				localBTDevice.setEnabled(true);
	        	return true;
			case R.id.mnuBt_dis:
				localBTDevice.setEnabled(false);
	        	return true;
			case R.id.mnuQuit:
				finish();
	        	return true;
	        }
		}
		catch (Exception e){
			BTRemote.tooltip(getApplicationContext(), "Error.");
		}
		return false;
	}

	/**
	 * 
	 * @param v
	 * @throws Exception 
	 */
	public void onClick(View v){
		
		try {
			if(localBTDevice.isEnabled()){
				switch(v.getId()){
				case R.id.btnBack:
					sendKey(BACK);
					break;
				case R.id.btnBas:
					sendKey(DOWN);
					break;
				case R.id.btnCentre:
					sendKey(ENTER);
					break;
				case R.id.btnDroite:
					sendKey(RIGHT);
					break;
				case R.id.btnFwd:
					sendKey(FORWARD);
					break;
				case R.id.btnGauche:
					sendKey(LEFT);
					break;
				case R.id.btnHaut:
					sendKey(UP);
					break;
				case R.id.btnMute:
					sendKey(MUTE);
					break;
				case R.id.btnNext:
					sendKey(NEXT);
					break;
				case R.id.btnPlay:
					sendKey(PLAY);
					break;
				case R.id.btnPrev:
					sendKey(PREVIOUS);
					break;
				case R.id.btnRwd:
					sendKey(REWIND);
					break;
				case R.id.btnStop:
					sendKey(STOP);
					break;
				case R.id.btnVolDown:
					sendKey(VOL_DOWN);
					break;
				case R.id.btnVolUp:
					sendKey(VOL_UP);
					break;
				case R.id.btnFullscreen:
					sendKey(FULLSCREEN);
					break;
				case R.id.btnMenu:
					sendKey(MENU);
					break;
//				case R.id.btnShutDown:
//					sendKey(SHUTDOWNMENU);
//					break;
				case R.id.btnInfo:
					sendKey(INFO);
					break;
				case R.id.btnMenuContext:
					sendKey(CONTEXTMENU);
					break;
				default:

				}
			}
		} catch (Exception e) {
			BTRemote.tooltip(getApplicationContext(), "Error retriving bt state.");
		}
	}

	/**
	 * 
	 * @param val
	 */
	private void sendKey(int val){
		try {
			output.write(val);
		} catch (IOException e) {
			BTRemote.tooltip(getApplicationContext(), "Error writing to outpustream.");
		}
	}
	
	private void showWaitDialog(int resString){
		dialog.setIndeterminate(true);
		dialog.setCancelable(false);
		dialog.setMessage(getString(resString));
		dialog.show();
	}

	@Override
	public void onClick(DialogInterface dialogInterface, int which) {
		if(which==DialogInterface.BUTTON_POSITIVE){
			try {
				localBTDevice.setEnabled(true);
				localBTDevice.setListener(adapter);
				showWaitDialog(R.string.enabling_bt);
			} catch (BluetoothException e) {
				BTRemote.tooltip(getApplicationContext(), "Bluetooth can't be turned ON.");
			}
		}
	}
}